﻿// owner 蒋家伟

#pragma once

// jsdk
#include "JsonUtils.h"
#include "DBSchemaObject.h"
#include "CommonFieldDescriptor.h"
#include "ObjectReflectDefine.h"
#include "Dbg_Warn_Define.h"

namespace jsdk
{
    // 类别描述 : OwnerPtr字段描述符，泛化版本存储的是继承于DBSchemaObject的类对象的其他接口类型(多继承)
    template<typename T, bool = std::is_base_of<DBSchemaObject, is_OwnerPtr<T>::ValueType>::value>
    class OwnerPtrObjectFieldDescriptor : public CommonFieldDescriptor
    {
        using valueType = T;
        static_assert(is_OwnerPtr<valueType>::value, "DBObject字段只接受智能指针包装的对象");
        using Ownerptr_Value_type = typename is_OwnerPtr<valueType>::ValueType;
        static_assert(is_define_quick_cast<Ownerptr_Value_type>::value, "DBObject字段只接受支持quick_cast的对象");
    public:
        /// \ brief 创建类别字段描述符
        /// \ in variableName   变量名称
        /// \ in offset         相对偏移
        /// \ in typeName       类别名称
        /// \ in typeUid        类型的唯一uid，取决于是否定义
        OwnerPtrObjectFieldDescriptor(const std::wstring& variableName, uint64_t offset, const std::wstring& typeName) :
            CommonFieldDescriptor(variableName, offset, typeid(valueType).hash_code(), typeName) {}

    private:
        // 重新实现
        virtual jsdk::OwnerPtr<DBSchemaObject> getCastDBSchemaObject(jsdk::OwnerPtr<DBSchemaObject> opSourceDBSchemaObject) const noexcept override
        {
            return CommonFieldDescriptor::castDBSchemaObject<Ownerptr_Value_type>(transformOwnerShip(opSourceDBSchemaObject));
        }

        virtual bool serializeValue(JsonDocument& jsonDoc, JsonObject& jsonObject) const noexcept override
        {
            const valueType* pValue = IClassFieldDescriptor::get<valueType>();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pValue, CommonFieldDescriptor::getErrorMsgPrefix() + L"获取存储值时发生异常", L"蒋家伟", L"2023-11-30");

            // 存储了空指针什么也不做, 需要写入一个空的uid, 但不需要不加入s_pValue_Key
            if (*pValue == nullptr)
            {
                // 需要写入空的uid
                JsonUtils::insert(jsonDoc, jsonObject, CommonFieldDescriptor::s_pClassUid_Key, JsonUtils::getDataStream(UniqueId::s_InvalidUId, jsonDoc));
                return true;
            }

            const DBSchemaObject* pDBSchemaObject = quick_cast<DBSchemaObject>((*pValue).get());
            DBG_WARN_AND_RETURN_FALSE_UNLESS(pDBSchemaObject, CommonFieldDescriptor::getErrorMsgPrefix() + L"必须要继承DBSchemaObject才可以序列化", L"蒋家伟", L"2023-11-30");

            const jsdk::UniqueId& uid = pDBSchemaObject->getClassId();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(uid.isValid(), CommonFieldDescriptor::getErrorMsgPrefix() + L"不为空，但是获取反射对象UID失败", L"蒋家伟", L"2023-11-30");

            bool success = pDBSchemaObject->serialize(jsonDoc, jsonObject);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(success, CommonFieldDescriptor::getErrorMsgPrefix() + L"序列化失败UID:" + uid.toString(), L"蒋家伟", L"2023-11-30");

            return true;
        }

        virtual bool unserializeValue(const JsonObject& object) noexcept override
        {
            jsdk::UniqueId uid;
            bool success = CommonFieldDescriptor::getClassUidFromJsonObject(object, uid);
            DBG_WARN_AND_RETURN_FALSE_UNLESS(success, CommonFieldDescriptor::getErrorMsgPrefix() + L"缺少类别描述", L"蒋家伟", L"2023-12-07");
            if (uid.isValid())
            {
                OwnerPtr<jsdk::DBSchemaObject> opDBSchemaObject = ObjectReflectUtils::getObjectReflectImp(uid, nullptr);
                DBG_WARN_AND_RETURN_FALSE_UNLESS(opDBSchemaObject, CommonFieldDescriptor::getErrorMsgPrefix() + L"类别对象无法反射, 其UID:" + uid.toString(), L"蒋家伟", L"2023-11-30");
                const jsdk::JsonValue* pJsonValue = JsonUtils::getJsonValue(object, s_pValue_Key);
                DBG_WARN_AND_RETURN_FALSE_UNLESS(pJsonValue, CommonFieldDescriptor::getErrorMsgPrefix() + L"反流对象不是Object, 其UID:" + uid.toString(), L"蒋家伟", L"2023-11-30");
                success = opDBSchemaObject->unserialize(*pJsonValue);
                DBG_WARN_AND_RETURN_FALSE_UNLESS(success, CommonFieldDescriptor::getErrorMsgPrefix() + L"反流对象失败, 其UID为:" + uid.toString() , L"蒋家伟", L"2023-11-30");
                return IClassFieldDescriptor::set(transformOwnerShip(opDBSchemaObject));
            }
            else
            {
                DBG_WARN_AND_RETURN_FALSE_UNLESS(JsonUtils::hasMember(object, s_pValue_Key) == false, CommonFieldDescriptor::getErrorMsgPrefix() + L"类对象无法识别且有数据对象", L"蒋家伟", L"2023-11-30");
            }
            return true;
        }
    };
}
